#include "GameLayer.h"
#include <tcResource/tc_resource.h>
#include <tcDatabase/tc_chessboard.h>
#include <tcInput/tc_input.h>
#include <tcPhysics/tc_physics.h>
#include <tcLogic/tc_logic.h>

#pragma warning(disable: 4244)
#pragma warning(disable: 4800)
#pragma warning(disable: 4305)

GameLayer::GameLayer(void) {}
GameLayer::~GameLayer(void) {}

CCScene* GameLayer::scene()
{
	CCScene *scene = CCScene::node();
	CCSize screenSize = CCDirector::sharedDirector()->getWinSize();

	{
		CCLayer *backgroundLayer = CCLayer::node();
		char path[128];
		tc_resource_get_path(TC_IMG_BG, path);
		CCSprite *background = CCSprite::spriteWithFile(path);
		background->setPosition(ccp(screenSize.width/2, screenSize.height/2));
		backgroundLayer->addChild(background, 1);
		scene->addChild(backgroundLayer);
	}

	{
		GameLayer *layer = GameLayer::node();
		scene->addChild(layer);
	}

	return scene;	
}

bool GameLayer::init()
{
	CCLayer::init();
	this->setIsTouchEnabled(true);

	this->load();
	scheduleUpdate();
	return true;
}

void GameLayer::load()
{
	this->restart(TC_PLAYER_ONE);

	this->createBackground();
	this->createHinges();
	this->createChessmenSprites();
	this->createTurnMarkSprites();
	this->createGameOverSprites();
	this->createPropImages();
	this->createPropButtons();
}

void GameLayer::createBackground()
{
	CCSize screenSize = CCDirector::sharedDirector()->getWinSize();
	char path[128];
	tc_resource_get_path(TC_IMG_CHESSBOARD, path);
	CCSprite *chessboard = CCSprite::spriteWithFile(path);
	chessboard->setPosition(ccp(screenSize.width/2, screenSize.height/2));
	this->addChild(chessboard, 1);
}


void GameLayer::createHinges()
{
	char path[128];
	tc_resource_get_path(TC_IMG_HINGE, path);

	CCSize screenSize = CCDirector::sharedDirector()->getWinSize();
	int hinge_intervals[] = {75, -75};
	tc_vector2 position;

	for (int i = 0; i < 2; i++)
	{
		CCSprite *hingeA = CCSprite::spriteWithFile(path);
		hingeA->setPosition(ccp(screenSize.width/2 - hinge_intervals[i], screenSize.height/2));
		this->addChild(hingeA, 1);

		position.x = hingeA->getPosition().x;
		position.y = hingeA->getPosition().y;
		tc_physics_create_hinge(position, hingeA->getContentSize().width, hingeA->getContentSize().height);
	}
}

void GameLayer::createTurnMarkSprites()
{
	float heights[2] = {57, 423};
	char path[128];
	tc_resource_get_path(TC_IMG_TURNMARK, path);
	for (int i = 0; i < 2; i++)
	{
		mTurnMarkSprites[i].initWithFile(path);
		mTurnMarkSprites[i].setIsVisible(false);
		mTurnMarkSprites[i].setPosition(ccp(160, heights[i]));
		this->addChild(&mTurnMarkSprites[i], 0);
	}
}

void GameLayer::createGameOverSprites()
{
	char path[128];
	tc_resource_get_path(TC_IMG_GAMEOVER, path);
	for (int i = 0; i < 2; i++)
	{
		mGameOverSprites[i].initWithFile(path, CCRectMake(0, 200*i, 200, 200));
		mGameOverSprites[i].setOpacity(0);
		mGameOverSprites[i].setPosition(ccp(160, 240));
		this->addChild(&mGameOverSprites[i], 4);
	}

	tc_resource_get_path(TC_IMG_STAR, path);
	mGameOverStarSprite.initWithFile(path, CCRectMake(0, 0, 200, 200));
	mGameOverStarSprite.setOpacity(0);
	mGameOverStarSprite.setPosition(ccp(160, 240));
	this->addChild(&mGameOverStarSprite, 4);
}

void GameLayer::createChessmenSprites()
{
	tcType images[32] = {
		TC_IMG_DEER, TC_IMG_CRUTCH, TC_IMG_CRUTCH, TC_IMG_HAT,
		TC_IMG_HAT, TC_IMG_SOCK, TC_IMG_SOCK, TC_IMG_HAT, 
		TC_IMG_HAT, TC_IMG_BELL, TC_IMG_BELL, TC_IMG_SNOW,
		TC_IMG_SNOW, TC_IMG_SNOW, TC_IMG_SNOW, TC_IMG_SNOW,
		TC_IMG_HORSE, TC_IMG_CRUTCH, TC_IMG_CRUTCH, TC_IMG_LEAF,
		TC_IMG_LEAF, TC_IMG_PRESENT, TC_IMG_PRESENT, TC_IMG_LEAF, 
		TC_IMG_LEAF, TC_IMG_COOKIEMAN, TC_IMG_COOKIEMAN, TC_IMG_SNOW,
		TC_IMG_SNOW, TC_IMG_SNOW, TC_IMG_SNOW, TC_IMG_SNOW,
	};

	for (int id = 0; id < TC_CHESSMEN_MAX_NUMBER; id++)
	{
		ChessmanSprite *sprite = new ChessmanSprite;
		sprite->init(id, images[id]);
		sprite->update();
		this->addChild(sprite, 2);
		this->addChild(sprite->getGunsightSprite(), 3);
		sprite->release();
		mChessmanSprites.push_back(sprite);
	}
}

void GameLayer::createPropImages()
{
	tcType images[] = {
		TC_IMG_POWERUP_SHOW,
		TC_IMG_FORBIT_SHOW,
		TC_IMG_ENLARGE_SHOW,
		TC_IMG_CHANGE_SHOW,
	};
	char path[128];
	for (int i = 0; i < TC_PROP_COUNT; i++)
	{
		tc_resource_get_path(images[i] ,path);
		mPropImages[i].initWithFile(path);
		mPropImages[i].setOpacity(0);
		mPropImages[i].setPosition(ccp(160, 240));
		this->addChild(&mPropImages[i], 3);
	}
}

void GameLayer::createPropButtons()
{
	tcType types[] = {TC_PROP_POWERUP, TC_PROP_FORBID, TC_PROP_ENLARGE, TC_PROP_CHANGE,
					  TC_PROP_POWERUP, TC_PROP_FORBID, TC_PROP_ENLARGE, TC_PROP_CHANGE};
	tcType images[] = {TC_IMG_POWERUP, TC_IMG_FORBID, TC_IMG_ENLARGE, TC_IMG_CHANGE,
	   				  TC_IMG_POWERUP, TC_IMG_FORBID, TC_IMG_ENLARGE, TC_IMG_CHANGE};
	float xs[] = {55, 125, 195, 265, 265, 195, 125, 55};
	float ys[] = {25, 25, 25, 25, 455, 455, 455, 455};
	float owners[] = {TC_PLAYER_ONE, TC_PLAYER_ONE, TC_PLAYER_ONE, TC_PLAYER_ONE, 
				      TC_PLAYER_TWO, TC_PLAYER_TWO, TC_PLAYER_TWO, TC_PLAYER_TWO};

	char path[128];
	for (int i = 0; i < 8; i++) {
		PropSprite &buttonSprite = mPropButtons[i];
		tc_resource_get_path(images[i], path);
		buttonSprite.initWithFile(path);
		buttonSprite.init(types[i], owners[i]);
		buttonSprite.setPosition(ccp(xs[i], ys[i]));
		buttonSprite.setScale(0.85);
		if (i >= 4)
		{
			buttonSprite.setRotation(180);
		}
		this->addChild(&buttonSprite, 0);
	}
}


bool GameLayer::ccTouchBegan( CCTouch *pTouch, CCEvent *pEvent )
{
	CCPoint location = pTouch->locationInView(pTouch->view());
	location = CCDirector::sharedDirector()->convertToGL(location);

	for (int i = 0; i < 8; i++)
	{
		PropSprite& propButton = mPropButtons[i];
		if (propButton.containsTouchLocation(location))
		{
			if (!tc_logic_get_valid())
			{
				return false;
			}

			if (tc_logic_use_prop(propButton.getPropType(), propButton.getOwner()))
			{
				//this->showPropImage(propButton.getPropType());
				break;
			}
			return false;
		}
	}

	tc_vector2 pos;
	pos.x = location.x;
	pos.y = location.y;

	return tc_input_mouse_down(pos);
}

void GameLayer::ccTouchMoved( CCTouch *pTouch, CCEvent *pEvent )
{
	CCPoint location = pTouch->locationInView(pTouch->view());
	location = CCDirector::sharedDirector()->convertToGL(location);

	tc_vector2 pos;
	pos.x = location.x;
	pos.y = location.y;

	tc_input_mouse_move(pos);
}

void GameLayer::ccTouchEnded( CCTouch *pTouch, CCEvent *pEvent )
{
	CCPoint location = pTouch->locationInView(pTouch->view());
	location = CCDirector::sharedDirector()->convertToGL(location);

	tc_vector2 pos;
	pos.x = location.x;
	pos.y = location.y;

	tc_input_mouse_up(pos);
}

void GameLayer::onEnter()
{
	CCLayer::onEnter();
	CCTouchDispatcher::sharedDispatcher()->addTargetedDelegate(this, 0, true); //why
}

void GameLayer::restartCallback()
{
	this->unscheduleUpdate();
	vector<ChessmanSprite *>::iterator it = mChessmanSprites.begin();
	for (; it != mChessmanSprites.end(); it++)
	{
		(*it)->reset();
	}

	this->runAction(CCSequence::actions(CCDelayTime::actionWithDuration(1.2f),
		CCCallFunc::actionWithTarget(this, callfunc_selector(GameLayer::chessmenMovedToInitialPositionCallback)), NULL));
}

void GameLayer::chessmenMovedToInitialPositionCallback()
{
	this->restart(TC_PLAYER_ONE);
}

void GameLayer::restart( tcType player )
{
	mCurrentPlayer = -1;
	mGameOverAnimationDone = false;
	tc_logic_restart(player);
	this->scheduleUpdate();
}

void GameLayer::update( ccTime dt )
{
	tc_logic_update(dt);

	this->updateChessmenSprites();
	this->updateTurn();
	this->updateGameState();
	this->updatePropImages();
}

void GameLayer::draw()
{
	int playerOneScore = tc_logic_get_player_score(TC_PLAYER_ONE);
	int playerTwoScore = tc_logic_get_player_score(TC_PLAYER_TWO);

	for (int i = 0; i < 8; i++)
	{
		mPropButtons[i].drawCDRect( i < 4 ? playerOneScore : playerTwoScore );
	}
}

void GameLayer::updateGameState()
{
	tcType gameState = tc_logic_get_game_state();

	CCActionInterval *scaleTo = CCScaleTo::actionWithDuration(0.5f, 1.0f);
	if (!mGameOverAnimationDone)
	{
		if (gameState == TC_GS_PLAYER_ONE_WIN || gameState == TC_GS_PLAYER_TWO_WIN)
		{
			if (gameState == TC_GS_PLAYER_ONE_WIN)
			{
				mGameOverStarSprite.setScale(0.01f);
				mGameOverStarSprite.setOpacity(255);
				CCActionInterval *starRotate = CCRotateBy::actionWithDuration(0.3f, 360.0f);
				CCActionInterval *starScaleTo = CCScaleTo::actionWithDuration(0.5f, 1.0f);
				mGameOverStarSprite.runAction(CCSequence::actions(CCRepeat::actionWithAction(starRotate, 10),
					CCFadeOut::actionWithDuration(0.5f), NULL));
				mGameOverStarSprite.runAction(starScaleTo);
			}
			mGameOverSprites[gameState].setScale(0.01f);
			mGameOverSprites[gameState].setOpacity(255);
			mGameOverSprites[gameState].runAction(CCSequence::actions(scaleTo,
				CCDelayTime::actionWithDuration(2.5f),
				CCFadeOut::actionWithDuration(0.5f),
				CCCallFunc::actionWithTarget(this, callfunc_selector(GameLayer::restartCallback)), NULL));

			mGameOverAnimationDone = true;
		}
	}
}

void GameLayer::updateTurn()
{
	tcType playerNow = tc_logic_get_current_player();
	if (playerNow != mCurrentPlayer)
	{
		mCurrentPlayer = playerNow;
		mTurnMarkSprites[mCurrentPlayer].setIsVisible(true);
		mTurnMarkSprites[!mCurrentPlayer].setIsVisible(false);
	}
}

void GameLayer::updateChessmenSprites()
{
	vector<ChessmanSprite *>::iterator it = mChessmanSprites.begin();
	for (; it != mChessmanSprites.end(); it++)
	{
		(*it)->update();
	}
}

void GameLayer::showPropImage( tcType propID )
{
	//if(mBrain.getCurrentPlayer() == PLAYER_TWO)
	//	this->mPropImage[category]->setRotation(180);
	mPropImages[propID].setOpacity(255);
	mPropImages[propID].runAction(CCFadeOut::actionWithDuration(1.0f));
}

void GameLayer::updatePropImages()
{
	static tcType prevState = 0;
	tcType currState = tc_logic_get_game_state();
	if (currState != prevState)
	{
		if (currState >= 4)
		{
			this->showPropImage(currState-4);
		}
		prevState = currState;
	}

}
